/*
 * AffixHClass.java
 *
 * Created on November 5, 2007, 7:43 AM
 *
 */
package org.osdtsystem.hierarchy;

/**
 * A class representing a suffix or a prefix. 
 * @author Martin Haulrich and Matthias Buch-Kromann
 */
public class AffixHClass extends AbstractHClass {
    // Variables
    final String affix;
    final int hash;
    public final static AffixHClass topClass = new AffixHClass(true);
    public final static AffixHClass emptyClass = new AffixHClass(false);

    /**
     * Constructor.
     * @param affix the affix associated with this class
     * @param terminal 
     */
    AffixHClass(String affix, boolean terminal) {
        this.affix = affix;
        hash = terminal ? Math.abs(affix.hashCode()) : - Math.abs(affix.hashCode()) - 1;
    }

    private AffixHClass(boolean top) {
        this.hash = top ? 0 : -1;
        this.affix = top ? "" : null;
    }

    public String affix() {
        return affix;
    }

    public boolean isTerminal() {
        return hash < 0;
    }

    public boolean isEmptyClass() {
        return this == emptyClass;
    }

    public boolean isTopClass() {
        return this == topClass;
    }

    @Override
    public int depth() {
        // Is this the top class or the empty class?
        if (affix == null) {
            if (isEmptyClass())
                return Integer.MAX_VALUE;
            if (isTopClass())
               return 0;
        }

        // For all other classes, the depth is the length of the affix
        return affix.length();
    }

    @Override
    public final int hashCode() {
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final AffixHClass other = (AffixHClass) obj;
        if (this.hash != other.hash) {
            return false;
        }
        if ((this.affix == null) ? (other.affix != null) : !this.affix.equals(other.affix)) {
            return false;
        }
        return true;
    }
}
